package com.handydata.antifraud.rule;

import com.bstek.urule.Utils;
import com.bstek.urule.runtime.KnowledgePackage;
import com.bstek.urule.runtime.KnowledgeSession;
import com.bstek.urule.runtime.KnowledgeSessionFactory;
import com.bstek.urule.runtime.service.KnowledgeService;
import com.handydata.antifraud.common.exception.RuleNotFoundException;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.util.Objects;
import java.util.function.Consumer;

/**
 *
 * 规则引擎调用类
 * @author guolong
 * @version $Id: RuleEngineInvoker.java, v 0.1 2019年5月1日 上午8:12:26 apple Exp $
 */
@Slf4j
public class RuleEngineInvoker {

	private KnowledgePackage knowledgePackage;

	//流程名称
	private String processName;

	//决策流包名
	@Getter()
	private String packageName;

	/**
	 *
	 * @param packageName 决策流包名
	 * @param processName 流程名称
	 */
	public RuleEngineInvoker(String packageName, String processName) {
		this.processName = processName;
		this.packageName=packageName;
		this.knowledgePackage = RuleEngineHolder.INSTANCE.getKnowledgePackage(packageName);
	}
	/**
	 *刷新规则文件，正在执行中去刷新有没有问题？
	 */
	public void refreshPackage(){
		this.knowledgePackage = RuleEngineHolder.INSTANCE.getKnowledgePackage(packageName);
	}

	/**
	 * 调用决策流
	 *
	 * @param consumer 输入输出变量放入到KnowledgeSession
	 * 格式：session -> {session.insert(inputVar);session.insert(outputVar);session.insert(middleVar);}
	 * @throws RuleNotFoundException
	 */
	public <R> void invokeDecision(Consumer<KnowledgeSession> consumer) throws RuleNotFoundException {
		Objects.requireNonNull(consumer);
		//通过取到的KnowledgePackage对象创建KnowledgeSession对象
		KnowledgeSession session = KnowledgeSessionFactory.newKnowledgeSession(knowledgePackage);
		consumer.accept(session);
		session.startProcess(processName);
	}

	enum RuleEngineHolder {
		INSTANCE;
		public KnowledgePackage getKnowledgePackage(String packageName) throws RuleNotFoundException {
			KnowledgeService service = (KnowledgeService)Utils.getApplicationContext().getBean(KnowledgeService.BEAN_ID);
			KnowledgePackage knowledgePackage;
			//通过KnowledgeService接口获取指定的资源包
			try {
				knowledgePackage = service.getKnowledge(packageName);
			} catch (Exception e) {
				throw new RuleNotFoundException("规则引擎资源包未发现，请确认配置是否正确:"+packageName+""+e);
			}
			return knowledgePackage;
		}
	}
}